package cn.touna.jss.modules.third.yixin;

import cn.touna.risk.api.contraints.facet.First;
import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.jss.common.properties.disconf.YiXinProperties;
import cn.touna.jss.common.util.ConvertUtil;
import cn.touna.jss.common.util.ValidUtil;
import cn.touna.jss.modules.third.yixin.util.YiXinUtil;
import cn.touna.jss.modules.adapter.ApiMapping;
import cn.touna.jss.modules.third.yixin.entity.YiXinRequestEntity;
import cn.touna.jss.common.util.SSLUtil;
import cn.touna.risk.api.domain.Response;
import cn.touna.risk.api.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 宜信接口
 * User: lijie
 * Email:lijiewj51137@touna.cn
 * Date: 2017/7/31
 * Time: 10:25
 */

@Service
public class YiXinService {
    private static final Logger logger = LogManager.getLogger(YiXinService.class);


    @Autowired
    private YiXinProperties yixinproperties;

    /**
     * 宜信-致诚阿福综合决策报告
     *
     * @param entity
     * @return
     */
    @ApiMapping(value = "YiXin.zhiChengDecision", desc = "宜信.致诚阿福综合决策报告")
    public Response zhiChengDecision(YiXinRequestEntity entity) {
        logger.info("REQ 【致诚阿福综合决策报告】 zhiChengDecision--> paramMap：{}", JSONObject.toJSONString(entity));
        Response response = ValidUtil.valid(entity);
        if (response != null) {
            return response;
        }

        response = new Response();
        Map<String, String> params = new HashMap<>();
        params.put("id_no", entity.getIdCard());
        params.put("name", entity.getName());
        params.put("mobile", entity.getMobile());
        params.put("bank_no", entity.getBankNo());
        params.put("corp_name", entity.getCompany());
        params.put("email", entity.getEmail());
        params.put("qq", entity.getQq());

        Map<String, String> body = new HashMap<>();
        body.put("user_name", yixinproperties.getYixinzhichengUserName());
        body.put("sign", yixinproperties.getYixinzhichengSignKey());
        body.put("api_name", yixinproperties.getYixinZhiChengCreditDecisionApiName());
        body.put("query_reason", entity.getQueryReason());
        body.put("Params", JSONObject.toJSONString(params));

        try {
            String result = HttpUtil.getInstance().post(yixinproperties.getYixinZhiChengCreditDecisionUrl(), body);
            logger.info("REQ【宜信致诚阿福综合决策报告】 zhiChengFraud--> resultjson：{}", result);
            return response.success(SystemErrorCodeEnum.SYSTEM_REQUEST_SUCC, result);
        } catch (Exception e) {
            logger.error("调用【宜信致诚阿福综合决策报告】异常,zhiChengFraud--> paramMap：{}", JSONObject.toJSONString(body), e);
            return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR);
        }

    }


    /**
     * 宜信-致诚阿福欺诈甄别
     *
     * @param entity
     * @return
     */
    @ApiMapping(value = "YiXin.zhiChengFraud", desc = "宜信.致诚阿福欺诈甄别")
    public Response zhiChengFraud(YiXinRequestEntity entity) {
        logger.info("REQ 【致诚阿福欺诈分】 zhiChengFraud--> paramMap：{}", JSONObject.toJSONString(entity));
        Response response = ValidUtil.valid(entity);
        if (response != null) {
            return response;
        }

        response = new Response();
        Map<String, String> params = new HashMap<>();
        params.put("amount_business", entity.getAmountBusiness());
        params.put("id_no", entity.getIdCard());
        params.put("name", entity.getName());
        params.put("mobile", entity.getMobile());
        params.put("bank_no", entity.getBankNo());
        params.put("corp_name", entity.getCompany());
        params.put("email", entity.getEmail());
        params.put("qq", entity.getQq());


        Map<String, String> body = new HashMap<>();
        body.put("user_name", yixinproperties.getYixinzhichengUserName());
        body.put("sign", yixinproperties.getYixinzhichengSignKey());
        body.put("api_name", yixinproperties.getYixinZhiChengCreditFraudApiName());
        body.put("query_reason", entity.getQueryReason());
        body.put("Params", JSONObject.toJSONString(params));

        try {
            String result = HttpUtil.getInstance().post(yixinproperties.getYixinZhiChengCreditFraudUrl(), body);
            logger.info("REQ 【宜信致诚阿福欺诈分】 zhiChengFraud--> resultjson：{}", result);
            return response.success(SystemErrorCodeEnum.SYSTEM_REQUEST_SUCC, result);
        } catch (Exception e) {
            logger.error("调用【宜信致诚阿福欺诈分】异常,zhiChengFraud--> paramMap：{}", JSONObject.toJSONString(body), e);
            return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR);
        }

    }


    /**
     * 宜信借款信息查询
     *
     * @param entity
     * @return
     */
    @ApiMapping(value = "YiXin.queryLoan", desc = "宜信.借款信息")
    public Response queryLoan(YiXinRequestEntity entity) {
        logger.info("REQ 【宜信借款信息查询】 queryLoan--> paramMap：{}", entity);
        Response<String> response = new Response<>();
        SortedMap<String, String> arguments = new TreeMap<String, String>();
        try {
            Response validResponse = ValidUtil.valid(entity, First.class);
            if (validResponse != null)
                return validResponse;
            entity.setQueryReason("10");
            arguments.putAll(ConvertUtil.convertBean2Map(entity));
            String result = HttpUtil.getInstance().post(yixinproperties.getUrlYixinQueryLoan(), getReqParam(arguments));
            logger.info("REQ 【宜信借款信息查询】 queryLoan--> resultjson：{}", result);
            return getResult(result);
        } catch (Exception e) {
            logger.error("调用【宜信借款信息查询】异常,queryLoan--> paramMap：{}", arguments, e);
            return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR);
        }
    }

    /**
     * 宜信查询黑名单
     *
     * @param entity
     * @return
     */
    @ApiMapping(value = "YiXin.queryBlackList", desc = "宜信.黑名单")
    public Response queryBlackList(YiXinRequestEntity entity) {
        logger.info("REQ 【宜信黑名单】 queryBlackList--> paramMap：{}", entity);
        Response<String> response = new Response<>();
        SortedMap<String, String> arguments = new TreeMap<String, String>();
        try {
            Response validResponse = ValidUtil.valid(entity, First.class);
            if (validResponse != null)
                return validResponse;
            entity.setQueryReason("10");
            arguments.putAll(ConvertUtil.convertBean2Map(entity));
            String result = HttpUtil.getInstance().get(yixinproperties.getUrlYixinQueryBlackList(), getReqParam(arguments));
            logger.info("REQ 【宜信黑名单】 queryLoan--> resultjson：{}", result);
            return getResult(result);
        } catch (Exception e) {
            logger.error("调用【宜信黑名单】异常,queryBlackList--> paramMap：{}", arguments, e);
            return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR);
        }
    }

    /**
     * 致诚分查询接口
     *
     * @param entity
     * @return
     */
    @ApiMapping(value = "YiXin.queryCreditScore", desc = "宜信.致诚分")
    public Response queryCreditScore(YiXinRequestEntity entity) {
        logger.info("REQ 【宜信致诚分查询接口】 queryCreditScore--> paramMap：{}", entity);
        Response<String> response = new Response<>();
        SortedMap<String, String> arguments = new TreeMap<String, String>();
        try {
            Response validResponse = ValidUtil.valid(entity, First.class);
            if (validResponse != null)
                return validResponse;
            entity.setQueryReason("10");
            arguments.putAll(ConvertUtil.convertBean2Map(entity));
            String result = HttpUtil.getInstance().get(yixinproperties.getUrlYixinGueryCreditScore(), getReqParam(arguments));
            logger.info("REQ 【宜信致诚分查询接口】 queryLoan--> resultjson：{}", result);
            return getResult(result);
        } catch (Exception e) {
            logger.error("gws调用【致诚分查询接口】异常,queryCreditScore--> paramMap：{}", arguments, e);
            return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR);
        }
    }

    /**
     * 宜信查询历史接口
     *
     * @param entity
     * @return
     */
    @ApiMapping(value = "YiXin.queriedHistory", desc = "宜信.查询历史")
    public Response queriedHistory(YiXinRequestEntity entity) {
        logger.info("REQ 【宜信查询历史接口】 queriedHistory--> paramMap：{}", entity);
        Response<String> response = new Response<>();
        SortedMap<String, String> arguments = new TreeMap<String, String>();
        try {
            Response validResponse = ValidUtil.valid(entity, First.class);
            if (validResponse != null)
                return validResponse;
            entity.setQueryReason("10");
            arguments.putAll(ConvertUtil.convertBean2Map(entity));
            String result = HttpUtil.getInstance().get(yixinproperties.getUrlYixinGetQueriedHistory(), getReqParam(arguments));
            logger.info("REQ 【宜信查询历史接口】 queryLoan--> resultjson：{}", result);
            return getResult(result);
        } catch (Exception e) {
            logger.error("调用【宜信查询历史接口】异常,queriedHistory--> paramMap：{}", arguments, e);
            return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR);
        }
    }

    /**
     * 宜信共享查询接口
     *
     * @param entity
     * @return
     */
    @ApiMapping(value = "YiXin.shareQuery", desc = "宜信.共享查询")
    public Response shareQuery(YiXinRequestEntity entity) {
        logger.info("REQ 【宜信共享查询接口】 shareQuery--> paramMap：{}", entity);
        Response<JSONObject> response = new Response<>();
        try {
            Response validResponse = ValidUtil.valid(entity, First.class);
            if (validResponse != null)
                return validResponse;
            final JSONObject params = new JSONObject();
            params.put("name", entity.getName());
            params.put("idNo", entity.getIdCard());
            params.put("queryReason", entity.getQueryReason());
            String result = sendRecvHttps("101", params);
            logger.info("REQ 【宜信共享查询接口】 shareQuery--> resultjson：{}", result);
            JSONObject jasonresult = JSONObject.parseObject(result);
            String msg = jasonresult.getString("message");
            String errorcode = jasonresult.getString("errorCode");
            if (null != jasonresult && ("0000".equals(errorcode) || ("0001".equals(errorcode)))) {
                return response.success(SystemErrorCodeEnum.SYSTEM_REQUEST_SUCC, jasonresult);
            } else {
                return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, msg, null);
            }
        } catch (Exception e) {
            logger.error("调用【宜信共享查询接口】异常,shareQuery--> paramMap：{},e:{}", entity, e.getMessage());
            return response.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR);
        }
    }


    private String sendRecvHttps(final String tx, final JSONObject data) throws Exception {
        final MultiValueMap<String, String> paraMap = new LinkedMultiValueMap<String, String>();
        final JSONObject innerJson = new JSONObject();
        innerJson.put("tx", tx);
        innerJson.put("data", data);

        logger.info("加密前数据：" + innerJson.toJSONString());
        paraMap.add("userid", yixinproperties.getUserid());
        final String sign = DigestUtils.md5Hex(yixinproperties.getUser() + yixinproperties.getPasswd());
        logger.info("待发送的sign:" + sign);
        paraMap.add("sign", sign);
        paraMap.add("params", innerJson.toJSONString());
        logger.info("请求参数url:{},paraMap:{}", yixinproperties.getApiUrlHttps(), paraMap);
        RestTemplate sender = new RestTemplate();
        SSLUtil.trustEveryone();
        final String res = sender.postForObject(yixinproperties.getApiUrlHttps(), paraMap, String.class);
        if (StringUtils.isBlank(res)) {
            logger.error("Return Nothing");
            return "没有返回任何信息";
        }
        logger.info("echo返回raw数据:" + res);
        return res;

    }


    /**
     * 宜信公共方法
     *
     * @param paramMap
     * @return
     * @throws Exception
     */
    private Map<String, String> getReqParam(Map<String, String> paramMap) throws Exception {
        String requstJson = JSON.toJSONString(paramMap);
        // 秘钥类
        RSAPublicKey rsaPublicKey = YiXinUtil.gainRSAPublicKey(yixinproperties.getPublicKeyStr());
        // 用公钥对uid进行RSA加密
        String encryptedUserID = YiXinUtil.encodeByRSAPublicKey(rsaPublicKey, yixinproperties.getUserid());
        // 定义map对象用来传递参数
        SortedMap<String, String> paraMap = new TreeMap<String, String>();
        paraMap.put("userid", encryptedUserID);
        // 将JSONstr进行RC4加密
        String encryptedParams = YiXinUtil.encodeByRC4(URLEncoder.encode(requstJson, "utf-8"), yixinproperties.getRc4key());
        paraMap.put("params", encryptedParams);
        return paraMap;
    }

    /**
     * 获取结果
     *
     * @return
     * @throws UnsupportedEncodingException
     */
    private Response getResult(String result) throws Exception {
        Response<JSONObject> response = new Response<>();
        JSONObject jasonresult = JSONObject.parseObject(result);
        String msg = "";
        if (jasonresult != null) {
            msg = (String) jasonresult.get("message");
        }
        String errorcode = jasonresult.getString("errorcode");
        if (null != jasonresult && ("0000".equals(errorcode) || ("0001".equals(errorcode)))) {
            String dataString = jasonresult.getString("data");
            // 用秘钥对得到的结果进行RC4解密
            String decryptResult = YiXinUtil.decodeByRC4(dataString, yixinproperties.getRc4key());
            decryptResult = URLDecoder.decode(decryptResult == null ? "" : decryptResult, "utf-8");
            return response.success(SystemErrorCodeEnum.SYSTEM_REQUEST_SUCC, JSONObject.parseObject(decryptResult));
        } else {
            //失败
            response.setMsg(msg);
            response.setCode(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR.getErrorCode());
        }
        return response;
    }


}
